package com.skivingcloud.security.conf;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;

import java.util.List;

/**
 * @author hushouquan
 */
@Configuration
@EnableMethodSecurity(securedEnabled = true)
@EnableWebSecurity
public class SecurityConfig{
    /**
     * 接口文档放行，生产阶段建议去掉
     */
    public static final List<String> DOC_WHITE_LIST = List.of("/doc.html", "/webjars/**", "/v3/api-docs/**");
    
    /**
     * 监控接口
     */
    public static final List<String> ACTUATOR_LIST = List.of("/actuator/**");
    @Value("${spring.profiles.active: 'dev'}")
    private String active;
    @Value("${skivingcloud.common.feign.accessToken:''}")
    private String feignAccessToken;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, SecurityAuthenticationHandler authenticationHandler) throws Exception{
        if("prod".equals(active)){
            http.authorizeHttpRequests(auth -> auth.requestMatchers(ACTUATOR_LIST.toArray(new String[0])).permitAll()
                            .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                            .requestMatchers(request -> feignAccessToken.equals(request.getHeader("feignAccessToken"))).permitAll()
                            .anyRequest().authenticated())
                    .csrf(AbstractHttpConfigurer::disable)
                    .sessionManagement(session -> session.maximumSessions(1).expiredSessionStrategy(authenticationHandler))
                    .exceptionHandling(exception -> exception.accessDeniedHandler(authenticationHandler).authenticationEntryPoint(authenticationHandler))
                    .httpBasic(Customizer.withDefaults());
        }else{
            http.authorizeHttpRequests(auth -> auth.requestMatchers(HttpMethod.GET, DOC_WHITE_LIST.toArray(new String[0])).permitAll()
                            .requestMatchers(ACTUATOR_LIST.toArray(new String[0])).permitAll()
                            .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                            .requestMatchers(request -> feignAccessToken.equals(request.getHeader("feignAccessToken"))).permitAll()
                            .anyRequest().authenticated())
                    .csrf(AbstractHttpConfigurer::disable)
                    .sessionManagement(session -> session.maximumSessions(1).expiredSessionStrategy(authenticationHandler))
                    .exceptionHandling(exception -> exception.accessDeniedHandler(authenticationHandler).authenticationEntryPoint(authenticationHandler))
                    .httpBasic(Customizer.withDefaults());
        }
        return http.build();
    }

}
